package com.timothy.service;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import com.timothy.android.util.XMLUtil;
import com.timothy.config.Configuration;
import com.timothy.service.MessageReceiveService.IncomingHandler;

import eneter.messaging.diagnostic.EneterTrace;
import eneter.messaging.endpoints.stringmessages.DuplexStringMessagesFactory;
import eneter.messaging.endpoints.stringmessages.IDuplexStringMessageSender;
import eneter.messaging.endpoints.stringmessages.IDuplexStringMessagesFactory;
import eneter.messaging.endpoints.stringmessages.StringResponseReceivedEventArgs;
import eneter.messaging.messagingsystems.messagingsystembase.IDuplexOutputChannel;
import eneter.messaging.messagingsystems.messagingsystembase.IMessagingSystemFactory;
import eneter.messaging.messagingsystems.tcpmessagingsystem.TcpMessagingSystemFactory;
import eneter.net.system.EventHandler;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;

public class CommunicationService extends Service {
	private static final String LOG_TAG = "CommunicationService";
	public final static String IP = "192.168.1.104";
	public final static String PORT = "9999";

	private IDuplexStringMessageSender mySender;

	private Handler myRefresh = new Handler();
	public String receiveMessageString;

	public static class MyRequest {
		public String Text;
	}

	public static class MyResponse {
		public int Length;
	}

	@Override
	public void onCreate() {
		Log.i("ServiceDemo", "CommunicationService.onCreate()...");
		super.onCreate();

		try {
			openConnection();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public void onStart(Intent intent, int startId) {
		Log.i("ServiceDemo", "CommunicationService.onStart()...");
		super.onStart(intent, startId);
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.i("ServiceDemo", "CommunicationService.onStartCommand()...");
		return super.onStartCommand(intent, flags, startId);
	}

	@Override
	public void onDestroy() {
		Log.i("ServiceDemo", "CommunicationService.onDestroy()...");
		super.onDestroy();

		mySender.detachDuplexOutputChannel();
	}

	// Binder given to clients
//	private final IBinder mBinder = new CommunicationBinder();


	/**
	 * Class used for the client Binder. Because we know this service always
	 * runs in the same process as its clients, we don't need to deal with IPC.
	 */
	/*public class CommunicationBinder extends Binder {
		public CommunicationService getService() {
			return CommunicationService.this;
		}
	}*/

	/*@Override
	public IBinder onBind(Intent intent) {
		return mBinder;
	}*/

	private void openConnection() throws Exception {
		Log.i("ServiceDemo", "CommunicationService.openConnection()...");

		// Create sender sending MyRequest and as a response receiving
		// MyResponse
		IDuplexStringMessagesFactory aSenderFactory = new DuplexStringMessagesFactory();
		mySender = aSenderFactory.createDuplexStringMessageSender();

		// Subscribe to receive response messages.
		mySender.responseReceived().subscribe(myOnResponseHandler);

		IMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory();
		IDuplexOutputChannel anOutputChannel = aMessaging.createDuplexOutputChannel("tcp://" + IP + ":" + PORT + "/");

		mySender.attachDuplexOutputChannel(anOutputChannel);
	}

	private EventHandler<StringResponseReceivedEventArgs> myOnResponseHandler = new EventHandler<StringResponseReceivedEventArgs>() {
		@Override
		public void onEvent(Object sender, StringResponseReceivedEventArgs e) {
			onResponseReceived(sender, e);
		}
	};

	/*private void onResponseReceived(Object sender,
			final StringResponseReceivedEventArgs e) {
		// Display the result - returned number of characters.
		// Note: Marshal displaying to the correct UI thread.
		myRefresh.post(new Runnable() {
			@Override
			public void run() {
				receiveMessageString = e.getResponseMessage();
				Log.i("ServiceDemo","CommunicationService.onResponseReceived().run()..."+ receiveMessageString);
			}
		});
	}*/
	
	private void onResponseReceived(Object sender,
			final StringResponseReceivedEventArgs e) {
		// Display the result - returned number of characters.
		// Note: Marshal displaying to the correct UI thread.
		myRefresh.post(new Runnable() {
			@Override
			public void run() {
//				receiveMessageString = e.getResponseMessage();
				
				StringBuffer commond = new StringBuffer();
				while (true) {
					String msg = e.getResponseMessage();
					Log.i("ServiceDemo","CommunicationService.onResponseReceived().run()..."+ msg);
					if ( msg != null ) {
						msg = msg.trim();
						if( msg.startsWith( COMMAND_START ) ) {
							commond.setLength(0);
							commond.append( msg );
						} else if( COMMAND_END.equalsIgnoreCase(msg) ){
							commond.append( msg );
							break;
						} else {
							commond.append( msg );
						}	
					} else {
						break;
					}
					processCommand( commond.toString() );
				}
			}
		});
	}

	// send message
	public void onSendRequest(String message) {
		// Send the request message.
		try {
			mySender.sendMessage(message);
		} catch (Exception err) {
			EneterTrace.error("Sending the message failed.", err);
		}
	}

	public String getReceiveMessageString() {
		return receiveMessageString;
	}
	
	public static final int MSG_SEND_SERVER = 0;	
	public static final int MSG_REGISTER_CLIENT = 1;
	public static final int MSG_UNREGISTER_CLIENT = 2;
	public static final int MSG_QUESTION = 3;
	public static final int MSG_BASE_STATION = 4;
    public static final int MSG_SHORT_MESSAGE = 5;
    public static final int MSG_SLIDE_RESULT = 6;
    public static final int MSG_CLEAR = 7;
    public static final int MSG_CONNECT_BASE = 8;
	
	private static final String COMMAND_START = "<Message";
	private static final String COMMAND_END = "</Message>";
	final Messenger rMessenger = new Messenger(new IncomingHandler());
	List<Messenger> sMessengers = new ArrayList<Messenger>();
	
    @Override
    public IBinder onBind(Intent intent) {
    	return rMessenger.getBinder();
    }
	
	private void processCommand(String command){
		Log.i(LOG_TAG,"----------------------processCommand start----------------------------");
		Object obj = null;
		int objType = 0;
	    String type = XMLUtil.getPropertyValue(command, "Type");
	    String content = XMLUtil.getChildren( command ).get(0);
	    
	    Log.i(LOG_TAG,"command:"+command);
	    Log.i(LOG_TAG,"type:"+type);
	    Log.i(LOG_TAG,"content:"+content);
	    
		if ("CommonQuestion".equals(type)) {
			obj = XMLUtil.getChildren(content).get(0);
			objType = MSG_QUESTION;
		} else if ("SlideResult".equals(type)) {
			obj = XMLUtil.getChildren(content).get(0);
			objType = MSG_SLIDE_RESULT;
		} else if ("Background".equals(type)) {
			String value = XMLUtil.getChildren(content).get(0);
			Configuration.background = XMLUtil.getElementValue(value);
		} else if ("BackLight".equals(type)) {
			String value = XMLUtil.getChildren(content).get(0);
			Configuration.backLight = Integer.valueOf(XMLUtil.getElementValue(value));
		} else if ("BubbleBackColor".equals(type)) {
			String value = XMLUtil.getChildren(content).get(0);
			Configuration.bubbleBackColor = XMLUtil.getElementValue(value);
		} else if ("ButtonBackColor".equals(type)) {
			String value = XMLUtil.getChildren(content).get(0);
			Configuration.buttonBackColor = XMLUtil.getElementValue(value);
		} else if ("BubbleFontColor".equals(type)) {
			String value = XMLUtil.getChildren(content).get(0);
			Configuration.bubbleFontColor = XMLUtil.getElementValue(value);
		} else if ("ButtonFontColor".equals(type)) {
			String value = XMLUtil.getChildren(content).get(0);
			Configuration.buttonFontColor = XMLUtil.getElementValue(value);
		} else if ("BubbleFontSize".equals(type)) {
			String value = XMLUtil.getChildren(content).get(0);
			Configuration.bubbleFontSize = Integer.valueOf(XMLUtil.getElementValue(value));
		} else if ("ButtonFontSize".equals(type)) {
			String value = XMLUtil.getChildren(content).get(0);
			Configuration.buttonFontSize = Integer.valueOf(XMLUtil.getElementValue(value));
		} else if ("BaseStations".equals(type)) {// List Base Stations
			obj = content;
			objType = MSG_BASE_STATION;
		} else if ("ConnectBase".equalsIgnoreCase(type)) {// Connect Base
			obj = XMLUtil.getElementValue(XMLUtil.getChildren(content).get(0));
			objType = MSG_CONNECT_BASE;
		} else if ("ShortMessage".equals(type)) {
			obj = XMLUtil.getElementValue(XMLUtil.getChildren(content).get(0));
			objType = MSG_SHORT_MESSAGE;
		} else if ("ScreenClear".equals(type)) {
			obj = XMLUtil.getElementValue(XMLUtil.getChildren(content).get(0));
			objType = MSG_CLEAR;
		} else if ("Deleted".equals(type)) {
			obj = XMLUtil.getElementValue(XMLUtil.getChildren(content).get(0));
			objType = MSG_CLEAR;
		}else if ("true".equalsIgnoreCase(type)) {
			obj = XMLUtil.getElementValue(XMLUtil.getChildren(content).get(0));
			objType = MSG_SHORT_MESSAGE;
		} else {
			Log.i(LOG_TAG, "Message can not be parsed");
		}
			
		if( obj != null ) {	
			for (int i=sMessengers.size()-1; i>=0; i--) {
	             try {
	            	 Log.i(LOG_TAG,"sMessengers.send "+i);
	            	 sMessengers.get(i).send( Message.obtain(null, objType, obj) );
	             } catch (RemoteException e) {
	            	 sMessengers.remove(i);
	             }
	        }
		}
		
		Log.i(LOG_TAG,"------------------------processCommand end--------------------------");
	}
	
	class IncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
        	Log.i(LOG_TAG,"IncomingHandler.handleMessage(): "+msg.what);
            switch (msg.what) {
                case MSG_REGISTER_CLIENT:
                    sMessengers.add(msg.replyTo);
                    Log.i(LOG_TAG,"MSG_REGISTER_CLIENT->msg.replyTo:"+msg.replyTo);
                    break;
                case MSG_UNREGISTER_CLIENT:
                    sMessengers.remove(msg.replyTo);
                    Log.i(LOG_TAG,"MSG_UNREGISTER_CLIENT->msg.replyTo:"+msg.replyTo);
                    break;
                case MSG_SEND_SERVER:
                    Log.i(LOG_TAG,"MSG_SEND_SERVER->msg.replyTo:"+msg.replyTo);
                    break;
            }
        }
    }
	

}